<?php

namespace App\Modules\Order\Models;


use App\Exceptions\StandardException;
use App\Library\Lock;
use App\Modules\Common\PhotoRank;
use App\Modules\Good\Models\Good;
use App\Modules\Good\Models\GoodSpec;
use App\Modules\Good\Models\UserBuyLimitRecord;
use App\Modules\Order\Jobs\FreeJob;
use App\Modules\Order\Jobs\UnlockJob;
use App\Modules\Package\Models\GoodPackage;
use App\Modules\Package\Models\PackageSpec;
use App\Modules\Payment\IOrder;
use App\Modules\Payment\Models\WeChatPay;
use App\Modules\Payment\Models\WeChatRefund;
use App\Modules\Rebate\Jobs\RebateJob;

use App\Modules\Rebate\NumberRank;
use App\Modules\Rebate\Rank;
use App\Modules\Recharge\RechargeRecord;
use App\Modules\Recharge\UserBalance;
use App\Modules\Shop\GoodsList;
use App\Modules\User\Manager;
use App\Modules\User\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Ramsey\Uuid\Uuid;

/**
 * Class Order
 * @package App\Modules\Order\Models
 * @property integer $type
 * @property integer $shop_id
 * @property integer $user_id
 * @property integer $pay_no
 * @property integer $link_id
 * @property integer $title
 * @property integer $price
 * @property integer $original_price
 * @property array $detail
 * @property integer $we_chat_pay
 * @property integer $we_chat_pay_time
 * @property integer $coupon_pay
 * @property integer $offline_pay
 * @property int $refund_fee
 * @property integer $status
 * @property string $mobile
 * @property string $name
 * @property string $address
 * @property string $deliver_date
 * @property int $referrer_id
 * @property int $delivery
 * @property string $cover
 * @property integer $rebate
 * @property string $remark
 * @property int $is_comment
 * @property int $is_finish
 * @property int $buyer_confirm
 * @property int $final_payment
 * @property array $bill
 * @property int $personal_id
 * @property string $referrer_level
 * @property string $gift
 * @property int $is_prepay
 */
class Order extends Model implements IOrder
{
    use SoftDeletes;

    const STATUS_INIT = "init";
    const STATUS_CLOSE = "close";
    const STATUS_PAID = "paid";
    const STATUS_REFUND = "refund";

    const TYPE_PACKAGE = 'package';
    const TYPE_GOOD = 'good';

    public static $statusShow = [
        self::STATUS_INIT => "待支付",
        self::STATUS_PAID => "已支付",
        self::STATUS_CLOSE => "已关闭",
        self::STATUS_REFUND => "全额退款",
    ];

    public static $deliveryShow = [
        0 => "到店自提",
        1 => "未发货",
        2 => "已发货",
    ];
    protected $fillable = [
        'type',
        'shop_id',
        'user_id',
        'pay_no',
        'link_id',
        'title',
        'price',
        'original_price',
        'detail',
        'we_chat_pay',
        'we_chat_pay_time',
        'coupon_pay',
        'offline_pay',
        'discount_amount',
        'refund_fee',
        'status',
        'mobile',
        'name',
        'address',
        'deliver_date',
        'referrer_id',
        'delivery',
        'cover',
        'remark',
        'is_comment',
        'is_finish',
        'buyer_confirm',
        'final_payment',
        'bill',
        'personal_id',
        'referrer_level',
        'gift',
        'is_prepay',
        'buyer_remark',
        'is_recharge',
        'is_balance',
        'balance_pay',
    ];

    protected $casts = [
        'detail' => "array",
        'bill' => "array",
        'gift' => 'array',
    ];

    public function __construct(array $attributes = [])
    {
        parent::__construct($attributes);
    }

    public function getPrice()
    {
//        if (env('APP_ENV') == 'test') {
//            return 0;
//        }
        if (ChangeOrderPrice::query()->where('new_pay_no', $this->pay_no)->exists()) {
            return $this->price;
        }
        if ($this->is_prepay) {
            return $this->price - $this->offline_pay;
        } else {
            // return $this->price - $this->discount_amount - $this->coupon_pay - $this->offline_pay;
            return $this->price - $this->discount_amount - $this->coupon_pay - $this->offline_pay - $this->balance_pay;//1031 by 余额支付
        }
    }

    public function active(int $money)
    {
        Lock::lock("order:{$this->id}", 2, function () use ($money) {
            DB::beginTransaction();

            $this->we_chat_pay = $money;
            $this->status = self::STATUS_PAID;
            $this->we_chat_pay_time = Carbon::now()->toDateTimeString();
            /** @var User $user */
            $user = User::query()->find($this->user_id);
            if ($user->has_order == 0) {
                $user->has_order = 1;
                $user->save();
            }
            $this->save();
            call_user_func([$this, $this->type . "Active"]);

            /**  是否使用充值支付  **/
            if($this->is_balance == 1){
                // 余额减少
                $userBalance = UserBalance::query()->where(["user_id" => $this->user_id, "shop_id" => $this->shop_id])->first();
                $balance = $userBalance->balance*100 - $this->balance_pay;
                // $balance = $userBalance->balance - ($order->getPrice() / 100);

                $good_id = $package_id = 0;
                if ($this->type == 'good') {
                    $aGoodOrPackage = Good::query()
                            ->where('id', $this->link_id)
                            ->select(['is_balance_pay','is_recharge','recharge_money'])
                            ->first();
                    $good_id = $this->link_id;
                }

                if ($this->type == 'package') {
                    $aGoodOrPackage = GoodPackage::query()
                            ->where('id', $this->link_id)
                            ->select(['is_balance_pay','is_recharge','recharge_money'])
                            ->first();
                    $package_id = $this->link_id;
                }

                // 使用充值消费，增加一条充值减少的记录
                $aRecord = [
                    'order_no'      => Uuid::uuid4()->getHex(),
                    'shop_id'       => $this->shop_id,
                    'user_id'       => $this->user_id,
                    'good_id'       => $good_id,
                    'package_id'    => $package_id,
                    'order_id'      => $this->id,
                    'total'         => -$this->balance_pay/100,
                    'status'        => 1,
                    'recharge_mode' => 2,//用户购买消费
                    'create_at'     => date('Y-m-d H:i:s'),
                    'update_at'     => date('Y-m-d H:i:s'),
                    'operator'      => '用户购买商品消费',
                    'order_id'      => $this->id,
                ];
                RechargeRecord::query()->create($aRecord);
                
                // 如果商品购买支持充值，则在充值记录表中增加记录   已改到完成订单后
                // if ($aGoodOrPackage->is_recharge == 1) {
                //     $data = [
                //         'order_no'      => Uuid::uuid4()->getHex(),
                //         'shop_id'       => $this->shop_id,
                //         'user_id'       => $this->user_id,
                //         'good_id'       => $good_id,
                //         'package_id'    => $package_id,
                //         'order_id'      => $this->id,
                //         'zs_money'      => $aGoodOrPackage->recharge_money/100,
                //         'total'         => $aGoodOrPackage->recharge_money/100,
                //         'status'        => 1,
                //         'recharge_mode' => 0,//用户购买充值
                //         'create_at'     => date('Y-m-d H:i:s'),
                //         'update_at'     => date('Y-m-d H:i:s'),
                //     ];

                //     RechargeRecord::query()->create($data);
                //     // 余额增加
                //     $balance = $balance + $data['zs_money']*100;
                // }
                UserBalance::query()
                    ->where(["user_id" => $this->user_id, "shop_id" => $this->shop_id])
                    ->update(["balance" => $balance/100]);
            }
            /**  是否使用充值支付  **/

            DB::commit();
//            if (!$this->is_prepay) {
//                dispatch(new RebateJob($this));
//            }
            
            //没有使用充值消费的，可以参与返利排名等
            // if ($this->is_balance != 1) { 
                if (!empty($this->referrer_id)) {
                    Rank::increaseAll($this->referrer_level, $this->referrer_id, $this->price);
                    NumberRank::increaseAll($this->referrer_level, $this->referrer_id);
                }
                if (!empty($this->personal_id)) {
                    Rank::increaseAll(3, $this->personal_id, $this->price);
                    NumberRank::increaseAll(3, $this->personal_id);
                }
            // }
        });
    }

    public function getType()
    {
        return self::class;
    }

    public static function getPayNo()
    {
        return Uuid::uuid4()->getHex();
    }


    public function finish($userOperation = "")
    {

        if ($this->is_finish) {
            return;
        }
        $this->is_finish = 1;

        dispatch(new RebateJob($this));

        $user = User::query()->find($this->user_id);
        if ($this->type == Order::TYPE_PACKAGE) {
            $goods = GoodPackage::query()->find($this->link_id);
            if ($this->detail['is_free']) { //如果是免费购-原始金额减去折扣金额
                $user->level = max($user->level, 1);
                Manager::setMember($user, $this->shop_id, $this->original_price - $this->discount_amount);

            }
        } elseif ($this->type == Order::TYPE_GOOD) {
            $goods = Good::query()->find($this->link_id);
            $tmp = 0;
            foreach ($this->detail as $value) {
                $tmp += $value['is_free'];
            }
            if ($tmp > 0) {
                $user->level = max($user->level, 1);
                Manager::setMember($user, $this->shop_id, $this->original_price - $this->discount_amount);
            }
        }
        $user->save();
        $this->save();

        /**
         * 临洮 - 增加解锁金额提醒
         * 增加的解锁金额：($this->original_price - $this->discount_amount)/100
         */
        if ($user->level == 1) { //只有返利会员有这个提醒

        }
        /**
         * 如果是买多少返多少的商品，增加用户余额
         */
        if (isset($goods) && $goods->is_recharge == 1) {
            $rechargeData = [
                "order_no" => Uuid::uuid4()->getHex(),
                "shop_id" => $this->shop_id,
                "user_id" => $user->id,
                "cz_money" => $goods->recharge_money / 100,
                "zs_money" => 0,
                "total" => $goods->recharge_money / 100,
                "operator" => "购买商品赠送的充值",
                "recharge_mode" => RechargeRecord::USER_RECHARGE,
                "status" => RechargeRecord::PAID,
            ];
            RechargeRecord::query()->create($rechargeData);
            $userBalance = UserBalance::query()->where(["user_id" => $user->id, "shop_id" => $this->shop_id])->first();
            if ($userBalance) {
                UserBalance::query()
                    ->where(["user_id" => $user->id, "shop_id" => $this->shop_id])
                    ->increment("balance", $goods->recharge_money / 100);
            } else {
                $userBalanceData = [
                    "user_id" => $user->id,
                    "shop_id" => $this->shop_id,
                    "balance" => $goods->recharge_money / 100,
                ];
                UserBalance::query()->create($userBalanceData);
            }
        }


        /**
         *  临洮：1、已交货，已确认收货
         *  模板ID：z5lZEXqBy0ZSy3OuHPmurQGDP9C2tChEDDKTRxm9i7M
         *  格式：
         * {{first.DATA}}
         * 订单号：{{keyword1.DATA}}
         * 完成状态：{{keyword2.DATA}}
         * 完成时间：{{keyword3.DATA}}
         * {{remark.DATA}}
         */
        if ($this->delivery == 0 && $this->is_prepay == 1) { //到店自取-定金支付
            if ($userOperation == "userOperation") {
                $sendData = [$user->openid, $this->id, "订单已确认收货", date("Y年m月d日 H时i分s秒")];
                sendMessage(18, $sendData);
                $user = User::query()
                    ->whereRaw("JSON_CONTAINS(shop_id, '\"" . $this->shop_id . "\"')")
                    ->where("is_palm_management", 1)
                    ->get(["openid", "is_palm_management"])->toArray();
                sendSystem($user, 50, $sendData);
            } else {
                $sendData = [$user->openid, $this->id, "订单已交货", date("Y年m月d日 H时i分s秒")];
                sendMessage(14, $sendData);
            }
        } elseif ($this->delivery == 0 && $this->is_prepay == 0) {//到店自取-全款支付
            if ($userOperation == "userOperation") {
                $sendData = [$user->openid, $this->id, "订单已确认收货", date("Y年m月d日 H时i分s秒")];
                sendMessage(19, $sendData);
                $user = User::query()
                    ->whereRaw("JSON_CONTAINS(shop_id, '\"" . $this->shop_id . "\"')")
                    ->where("is_palm_management", 1)
                    ->get(["openid", "is_palm_management"])->toArray();
                sendSystem($user, 51, $sendData);
            } else {
                $sendData = [$user->openid, $this->id, "订单已交货", date("Y年m月d日 H时i分s秒")];
                sendMessage(15, $sendData);
            }
        } elseif ($this->delivery > 0 && $this->is_prepay == 1) {//物流发货-定金支付
            $sendData = [$user->openid, $this->id, "订单已确认收货", date("Y年m月d日 H时i分s秒")];
            if ($userOperation == "userOperation") {
                sendMessage(20, $sendData);
                //给商家职员推送
                $user = User::query()
                    ->whereRaw("JSON_CONTAINS(shop_id, '\"" . $this->shop_id . "\"')")
                    ->where("is_palm_management", 1)
                    ->get(["openid", "is_palm_management"])->toArray();
                sendSystem($user, 44, $sendData);
            } else {
                sendMessage(22, $sendData);
            }
        } elseif ($this->delivery > 0 && $this->is_prepay == 0) {//物流发货-全款支付
            $sendData = [$user->openid, $this->id, "订单已确认收货", date("Y年m月d日 H时i分s秒")];
            if ($userOperation == "userOperation") {
                sendMessage(21, $sendData);
                //给商家职员推送
                $user = User::query()
                    ->whereRaw("JSON_CONTAINS(shop_id, '\"" . $this->shop_id . "\"')")
                    ->where("is_palm_management", 1)
                    ->get(["openid", "is_palm_management"])->toArray();
                sendSystem($user, 45, $sendData);
            } else {
                sendMessage(23, $sendData);
            }
        }
        return true;
    }

    public function goodActive()
    {
        foreach ($this->detail as $value) {
            GoodsList::query()->where('goods_type', GoodsList::TYPE_PACKAGE)->where('link_id', $value['good_id'])->increment('sales_volume');
            Good::query()->find($value['good_id'])->increment('sales_volume', $value['number']);
            GoodSpec::query()->find($value['id'])->increment('sales_volume', $value['number']);
            if (isset($value['buy_limit']) && $value['buy_limit'] > 0) {
                UserBuyLimitRecord::query()
                    ->create([
                        'user_id' => $this->user_id,
                        'order_id' => $this->id,
                        'goods_id' => $value["good_id"],
                        'number' => $value['number'],
                    ]);
            }
        }
    }

    public function packageActive()
    {
        $package = GoodPackage::query()->where('id', $this->link_id)->first();
        $package->increment('sales_volume');
        GoodsList::query()->where('goods_type', GoodsList::TYPE_PACKAGE)->where('link_id', $package->id)->increment('sales_volume');
        $specId = array_column($this->detail, 'id');
        PackageSpec::query()->whereIn('id', $specId)
            ->increment('sales_volume');
    }

    public function refund($money, $reason)
    {
        Lock::lock("order:{$this->id}", 2, function () use ($money, $reason) {
            $this->refresh();
            if ($money > $this->we_chat_pay - $this->refund_fee) {
                throw new StandardException('超出可退款金额');
            }
            $this->refund_fee += $money;
            if ($this->we_chat_pay == $this->refund_fee) {
                $this->status = self::STATUS_REFUND;
            }
            $this->save();
            $pay = WeChatPay::query()
                ->where('out_trade_no', $this->pay_no)
                ->where('user_id', $this->user_id)
                ->where('result_code', 'SUCCESS')
                ->first();

            /** @var WeChatRefund $weChatRefund */
            $weChatRefund = WeChatRefund::query()->create([
                "order_type" => self::class,
                "order_id" => $this->id,
                'out_trade_no' => $this->pay_no,
                'out_refund_no' => Uuid::uuid4()->getInteger(),
                'total_fee' => $pay->total_fee,
                'refund_fee' => $money,
                'refund_desc' => $reason,
                'refund_account' => config('wechat.payment.refund_account', 'REFUND_SOURCE_UNSETTLED_FUNDS'),
                'status' => WeChatRefund::STATUS_INITIALIZED
            ]);
            $weChatRefund->execute();
        });
    }

    public function close()
    {
        $this->status = self::STATUS_CLOSE;
        if ($this->type == self::TYPE_GOOD) {
            foreach ($this->detail as $value) {
                GoodSpec::query()->where('id', $value['id'])->increment('stock', $value['number']);
            }
            UserBuyLimitRecord::query()
                ->where([
                    'user_id' => $this->user_id,
                    'order_id' => $this->id,
                ])->delete();
        }

        $this->save();
    }

    public function refundFail($money)
    {
        Lock::lock("order:{$this->id}", 2, function () use ($money) {
            $this->refresh();
            $this->refund_fee -= $money;
            $this->status = self::STATUS_PAID;
            $this->save();
        });
    }


}
